#include "lucc.h"


static void dbi_err(dbpool_t *pool, MYSQL *sql)
{
	const char *msg;

	if(pool && sql) {
		pool->err = mysql_errno(sql);
		msg = mysql_error(sql);
		if(msg)
			str_copy(pool->errmsg, msg);
	}
}

int dbi_query(dbpool_t *pool, dbi_t *dbi, const char *format, ...)
{	
	char sql_cmd[4096];
	va_list ap;
	int ret;

	if(pool == NULL)
		return -1;

	if(dbi == NULL)
		return -2;

	memset(dbi, 0, sizeof(dbi_t));

	dbi->dbp = pool;
		
	va_start(ap, format);
	vsnprintf(sql_cmd, sizeof(sql_cmd) - 1, format, ap);
	va_end(ap);

	ret = dbpool_get(dbi->dbp, &dbi->sql);
	if(ret)
		return -3;

	if(mysql_query(dbi->sql, sql_cmd)) {
		dbpool_put(dbi->dbp, dbi->sql);
		dbi_err(pool, dbi->sql);
		return -4;
	}

	dbi->sql_res = mysql_store_result(dbi->sql);
	dbi->sql_row = NULL;
	return 0;
}

int dbi_fetch_row(dbi_t *dbi)
{
	if(dbi == NULL)
		return -1;
	
	if(dbi->sql == NULL)
		return -2;

	if(dbi->sql_res == NULL)
		return -3;
		
	dbi->sql_row = mysql_fetch_row(dbi->sql_res);

	return dbi->sql_row ? 1 : 0;
}

int dbi_fetch_col(dbi_t *dbi, int col, int type, void *value)
{
	if(dbi == NULL)
		return -1;

	if(dbi->sql == NULL)
		return -2;

	if(col < 0)
		return -3;

	if(value == NULL)
		return -4;

	if(dbi->sql_res == NULL)
		return -5;
		
	if(dbi->sql_row == NULL)
		return -6;

	switch(type) {
		case DBI_INT:
			if(dbi->sql_row[col] == NULL) {
				*(int *) value = 0;
				return 0;
			}
			*(int *) value = atoi(dbi->sql_row[col]);
			break;

		case DBI_LONG:
			if(dbi->sql_row[col] == NULL) {
				*(long *) value = 0;
				return 0;
			}
			*(long *) value = atol(dbi->sql_row[col]);
			break;
	
		case DBI_STR16:
			if(dbi->sql_row[col] == NULL) {
				*(char *) value = '\0';
				return 0;
			}
			str_ncopy((char *) value, dbi->sql_row[col], DBI_STR16);
			break;
		
		case DBI_STR32:
			if(dbi->sql_row[col] == NULL) {
				*(char *) value = '\0';
				return 0;
			}
			str_ncopy((char *) value, dbi->sql_row[col], DBI_STR32);
			break;

		case DBI_STR64:
			if(dbi->sql_row[col] == NULL) {
				*(char *) value = '\0';
				return 0;
			}
			str_ncopy((char *) value, dbi->sql_row[col], DBI_STR64);
			break;
			
		case DBI_STR128:
			if(dbi->sql_row[col] == NULL) {
				*(char *) value = '\0';
				return 0;
			}
			str_ncopy((char *) value, dbi->sql_row[col], DBI_STR128);
			break;
		
		case DBI_STR256:
			if(dbi->sql_row[col] == NULL) {
				*(char *) value = '\0';
				return 0;
			}
			str_ncopy((char *) value, dbi->sql_row[col], DBI_STR256);
			break;
		
		case DBI_STR512:
			if(dbi->sql_row[col] == NULL) {
				*(char *) value = '\0';
				return 0;
			}
			str_ncopy((char *) value, dbi->sql_row[col], DBI_STR512);
			break;

		case DBI_TEXT:
			if(dbi->sql_row[col] == NULL) {
				*(char *) value = '\0';
				return 0;
			}
			str_ncopy((char *) value, dbi->sql_row[col], DBI_TEXT);
			break;
			
		default:
			return -7;
	}
	
	return 1;
}

int dbi_query_str(dbpool_t *pool, char *value, int type, const char *format, ...)
{
	char sql_cmd[4096];
	dbi_t dbi;
	int retval = -1;
	va_list ap;
	int ret;
	
	if(pool == NULL)
		return -1;
	
	memset(&dbi, 0, sizeof(dbi));

	dbi.dbp = pool;

	va_start(ap, format);
	vsnprintf(sql_cmd, sizeof(sql_cmd) - 1, format, ap);
	va_end(ap);

	ret = dbi_query(pool, &dbi, sql_cmd);
	if(ret)
		return -2;

	ret = dbi_fetch_row(&dbi);
	if(ret <= 0) {
		retval = -3;
		goto RET;
	}
		
	ret = dbi_fetch_col(&dbi, 0, type, value);
	if(ret <= 0) {
		retval = -4;
		goto RET;
	}

	retval = 0;

RET:
	dbi_free(&dbi);
	
	return retval;
}

int dbi_query_ints(dbpool_t *pool, int *values, int num, const char *format, ...)
{
	char sql_cmd[4096];
	dbi_t dbi;
	int retval = -1;
	va_list ap;
	int ret;
	int i;
	
	if(pool == NULL)
		return -1;
	
	if(num <= 0)
		return -2;

	memset(&dbi, 0, sizeof(dbi));

	dbi.dbp = pool;

	va_start(ap, format);
	vsnprintf(sql_cmd, sizeof(sql_cmd) - 1, format, ap);
	va_end(ap);

	ret = dbi_query(pool, &dbi, sql_cmd);
	if(ret)
		return -3;

	ret = dbi_fetch_row(&dbi);
	if(ret <= 0) {
		retval = -4;
		goto RET;
	}
		
	for(i = 0 ; i < num ; i ++) {
		ret = dbi_fetch_col(&dbi, i, DBI_INT, &values[i]);
		if(ret <= 0) {
			retval = -5;
			goto RET;
		}
	}
	
	retval = 0;
	
RET:
	dbi_free(&dbi);
	return retval;
}

int dbi_execute(dbpool_t *pool, const char *format, ...)
{
	char sql_cmd[4096];
	dbi_t dbi;
	int retval = -1;
	va_list ap;
	int ret;
	
	if(pool == NULL) {
		return -1;
	}

	memset(&dbi, 0, sizeof(dbi));

	dbi.dbp = pool;

	va_start(ap, format);
	vsnprintf(sql_cmd, sizeof(sql_cmd) - 1, format, ap);
	va_end(ap);

	ret = dbpool_get(dbi.dbp, &dbi.sql);
	if(ret) {
		return -2;
	}

	if(mysql_query(dbi.sql, sql_cmd)) {
		dbi_err(pool, dbi.sql);
		retval = -3;
		goto RET;
	}

	retval = 0;
RET:
	dbi_free(&dbi);
	return retval;	
}

int dbi_free(dbi_t *dbi)
{
	if(dbi == NULL)
		return -1;

	if(dbi->sql_res) {
		mysql_free_result(dbi->sql_res);
		dbi->sql_res = NULL;
	}

	if(dbi->sql && dbi->dbp) {
		dbpool_put(dbi->dbp, dbi->sql);
		dbi->sql = NULL;
		dbi->dbp = NULL;
	}

	return 0;
}
